package com.thor.palmmall.impl.pay;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.axis.encoding.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tapestry.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.gson.Gson;
import com.thor.commons.exception.ThorServiceException;
import com.thor.commons.util.Assert;
import com.thor.commons.util.StringUtil;
import com.thor.palmmall.api.pay.unionmch.MutiChannelUnionMchService;
import com.thor.palmmall.api.statement.AStatementPayBill;
import com.thor.palmmall.api.statement.AStatementPayBillState;
import com.thor.palmmall.api.statement.StatementService;
import com.thor.palmmall.rest.event.StatementOrderSyncEvent;
import com.thor.palmmall.rest.user.AChannelContents;
import com.thor.palmmall.util.event.GlobalEventBus;
import com.thor.palmmall.util.pay.UnionPayUtil;

/**
 * 
 * @author liyang
 * 
 * @since 1.0
 *
 */
public class MutiChannelUnionMchServiceImpl implements MutiChannelUnionMchService {

  private final String NOTIFY_FLAG_SUCCESS = "success";
  private final String NOTIFY_FLAG_FAILED = "failed";
  private static final Logger logger = LoggerFactory
      .getLogger(MutiChannelUnionMchServiceImpl.class);

  @Override
  public String getUnionMchPayTradeNo(Map<String, String> params, AChannelContents channel)
      throws ThorServiceException {
    Assert.assertArgumentNotNull(params, "params");
    Map<String, String> contentData = new HashMap<String, String>();
    prepareParams(params, contentData, channel);
    try {

      // 1.对象转为json串
      String jsonStr = new Gson().toJson(contentData);

      // 2.base64编码
      String reqContent = Base64.encode(jsonStr.getBytes("utf-8"));

      // 3.md5加密
      String signature = DigestUtils.md5Hex(reqContent + channel.getMchKey());
      String path = channel.getAppRequestUrl() + String.format("?signature=%s&reqContent=%s",
          signature, URLEncoder.encode(reqContent, "utf-8"));
      logger.info("-------------------------------" + path);

      // 4.调用银联接口获取交易号
      Map<String, String> resp = UnionPayUtil.get(path, "utf-8");

      // 5.urldecode解码
      String respContent = URLDecoder.decode(resp.get("respContent"), "utf-8");
      // 6.base64解码
      String resContent = new String(Base64.decode(respContent), "utf-8");
      JSONObject respJson = new JSONObject(resContent);
      if (!"00".equals(respJson.getString("respCode"))) {
        throw new ThorServiceException(respJson.getString("respMsg"));
      }
      return respJson.getString("tn");
    } catch (Exception e) {
      throw new ThorServiceException(e.getMessage());
    }
  }

  @Override
  public boolean callBack(String request) {

    String respContent = null;
    try {
      // 获取银联通知服务器发送的后台通知参数
      Map<String, String> reqParam = getAllRequestParam(request);
      // urldecode解码
      respContent = URLDecoder.decode(reqParam.get("respContent"), "utf-8");
      // base64解码
      String resContent = new String(Base64.decode(respContent), "utf-8");
      JSONObject respJson = new JSONObject(resContent);
      String queryId = respJson.getString("queryId");
      String orderId = respJson.getString("orderId");
      String txnTime = respJson.getString("txnTime");

      AStatementPayBill bill = statementService.getByBillNumber(orderId);
      // 获取后台通知的数据，其他字段也可用类似方式获取
      if (bill == null) {
        return false;
      }
      if (bill.getState().equals(AStatementPayBillState.FINISH)) {
        return true;
      }
      if (StringUtil.isNullOrEmpty(queryId)) {
        bill.setNotifyFlag(NOTIFY_FLAG_FAILED);
        statementService.saveStatementPayBill(bill, bill.getCreateInfo());
        return false;
      }
      try {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss");
        bill.setActionTime(fmt.parse(txnTime));
      } catch (Exception e) {
        e.printStackTrace();
      }
      bill.setState(AStatementPayBillState.PAID);
      bill.setNotifyFlag(NOTIFY_FLAG_SUCCESS); // 回调使用单独的标志字段
      bill.setTransactioNo(queryId);
      statementService.saveStatementPayBill(bill, bill.getCreateInfo());
      // 开始同步订单任务
      StatementOrderSyncEvent event = new StatementOrderSyncEvent();
      event.setBill(bill);
      GlobalEventBus.post(event);
      return true;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return false;
  }

  private void prepareParams(Map<String, String> params, Map<String, String> contentData,
      AChannelContents channel) {
    Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
    while (iterator.hasNext()) {
      Map.Entry<String, String> entry = iterator.next();
      contentData.put(entry.getKey(), entry.getValue());
    }
    contentData.put("backUrl", channel.getBackUrl());
    contentData.put("merId", channel.getMerId());
  }

  /**
   * 获取请求参数中所有的信息
   * 
   * @param request
   * @return
   */
  public static Map<String, String> getAllRequestParam(final String request) {
    Map<String, String> res = new HashMap<String, String>();
    String[] keyValueArr = request.split("&");
    for (String value : keyValueArr) {
      String[] keyValue = value.split("=");
      if (keyValue.length >= 2) {
        res.put(keyValue[0], keyValue[1]);
      }
    }
    return res;
  }

  @Autowired
  private StatementService statementService;
}
